package com.example.dynamicdatabasedemo.config;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;


/**
 * @Description:
 * @Author: dengping.xu
 * @Data: 2021-07-23
 */
@Slf4j
public class DynamicDataSource extends AbstractRoutingDataSource {
    private static Map<Object, Object> dataSourceMap = new HashMap<>();
    private static Map<Long, DbMoudleConfig> errorDataSourceMap = new HashMap<>();

    public static DataSource createDataSource(DbMoudleConfig dbMoudleConfig) {
        try {
            return getDatabase(dbMoudleConfig);
        }catch (Exception exception){
            if(dbMoudleConfig.getId() == 0L){
                throw exception;
            }else {
                log.error("Database init error, database:" + dbMoudleConfig.getDatabase(), exception);
                return null;
            }
        }
    }

    private static DataSource getDatabase(DbMoudleConfig dbMoudleConfig) {
        HikariConfig config = new HikariConfig();
        config.setUsername(dbMoudleConfig.getUsername());
        config.setPassword(dbMoudleConfig.getPassword());
        config.setJdbcUrl(makeMySqlUrl(dbMoudleConfig));
        config.setMinimumIdle(1);
        config.setMaximumPoolSize(dbMoudleConfig.getMaxpoolsize());
//        config.setMaxLifetime(TimeUnit.SECONDS.toMillis(1740L));
        HikariDataSource hikariDataSource = new HikariDataSource(config);
        return hikariDataSource;
    }

    @Override
    public void setTargetDataSources(Map<Object, Object> targetDataSources) {
        super.setTargetDataSources(targetDataSources);
        dataSourceMap.putAll(targetDataSources);
        super.afterPropertiesSet();
    }

    private static String makeMySqlUrl(DbMoudleConfig dbModuleConfig) {
        StringBuilder sb = new StringBuilder();
        sb.append(dbModuleConfig.getProtocol());
        sb.append("://");
        sb.append(dbModuleConfig.getHost());
        sb.append(":");
        sb.append(dbModuleConfig.getPort());
        sb.append("/");
        sb.append(dbModuleConfig.getDatabase());
        sb.append("?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&autoReconnect=true&failOverReadOnly=false");
        return sb.toString();
    }

    public static boolean isExistDataSource(String key) {
        return dataSourceMap.containsKey(key);
    }

    public static DynamicDataSource getInstance() {
        return DynamicDataSource.SingletonHolder.instance;
    }


    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceHolder.getDataSourceKey();
    }

    public static Map<Object, Object> getDataSourceMap() {
        return dataSourceMap;
    }

    public static Map<Long, DbMoudleConfig> getErrorDataSourceMap() {
        return errorDataSourceMap;
    }

    private static class SingletonHolder {
        private static DynamicDataSource instance = new DynamicDataSource();

        private SingletonHolder(){
        }
    }
}
